package com.seer.auto.dao;


import com.seer.auto.utils.ClassUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.RowMapper;

@Data
@Slf4j
public class DefaultRowMapper<T> implements RowMapper<T> {

    private Class<T> clazz;

    public static<T> DefaultRowMapper<T> getRowMapper(Class<T> clazz) {
        final DefaultRowMapper<T> mapper = new DefaultRowMapper<>();
        mapper.setClazz(clazz);
        return mapper;
    }

    public static<T> DefaultRowMapper<T> getRowMapper(String allName)
        throws ClassNotFoundException {
        final DefaultRowMapper<T> mapper = new DefaultRowMapper<>();
        mapper.setClazz((Class<T>) Class.forName(allName));
        return mapper;
    }

    public static String getMethodName(Field f) {
        return "get" + ClassUtils.className(f.getName());
    }

    public static String setMethodName(Field f) {
        return "set" + ClassUtils.className(f.getName());
    }

    @SneakyThrows
    @Override
    public T mapRow(ResultSet rs, int rowNum) throws SQLException {
        T t = clazz.newInstance();
        for (Field f : clazz.getDeclaredFields()) {
            Method setMethod = clazz.getDeclaredMethod(setMethodName(f), f.getType());
            setMethod.invoke(t, getValue2(f, rs));
        }
        return t;
    }

    public Object getValue2(Field f, ResultSet rs) {
        try {
            int i = rs.findColumn(f.getName());
            return rs.getObject(i);
        } catch (SQLException e) {
            log.info("row mapper exception, error={}", e.getMessage());
            return null;
        }
    }

    public Object getValue(Field f, ResultSet rs) {
        try {
            switch (f.getType().getSimpleName()) {
                case "String":
                    return rs.getString(f.getName());
                case "Integer":
                    return rs.getInt(f.getName());
                case "Long":
                    return rs.getLong(f.getName());
                case "Boolean":
                    return rs.getBoolean(f.getName());
                case "Date":
                    return rs.getDate(f.getName());
                case "Time":
                    return rs.getTime(f.getName());
                case "Timestamp":
                    return rs.getTimestamp(f.getName());
                case "Float":
                    return rs.getFloat(f.getName());
                case "Double":
                    return rs.getDouble(f.getName());
                default:
                    return null;
            }
        } catch (Exception e) {
            log.info("row mapper error, error={}", e);
            return null;
        }
    }
}
